/**
`useImperativeHandle`  是 React 中的一个 Hook，通常与  `forwardRef`  一起使用。它允许你自定义通过  `ref`  传递给父组件的实例值。
  1. 基本概念
  - 自定义 ref： `useImperativeHandle`  使得你可以控制组件实例中暴露给父组件的值。默认情况下，使用  `ref`  访问的只是 DOM 元素或组件实例，但通过  `useImperativeHandle` ，你可以定义一个更复杂的对象。
  - 与  `forwardRef`  配合使用：为了使用  `useImperativeHandle` ，通常需要将组件包裹在  `forwardRef`  中，以便能够接收来自父组件的  `ref` 。

  2. 使用方式
   示例：自定义组件的 ref
  import React, { useImperativeHandle, useRef, forwardRef } from 'react';

  // 创建一个自定义组件
  const CustomInput = forwardRef((props, ref) => {
    const inputRef = useRef();

    // 使用 useImperativeHandle 自定义暴露给父组件的实例值
    useImperativeHandle(ref, () => ({
      focus: () => {
        inputRef.current.focus(); // 暴露 focus 方法
      },
      getValue: () => {
        return inputRef.current.value; // 暴露获取输入值的方法
      },
    }));

    return <input ref={inputRef} type="text" />;
  });

  // 父组件
  const ParentComponent = () => {
    const inputRef = useRef();

    const handleFocus = () => {
      inputRef.current.focus(); // 调用子组件暴露的 focus 方法
    };

    const handleGetValue = () => {
      alert(inputRef.current.getValue()); // 调用子组件暴露的获取值的方法
    };

    return (
      <div>
        <CustomInput ref={inputRef} />
        <button onClick={handleFocus}>Focus Input</button>
        <button onClick={handleGetValue}>Get Input Value</button>
      </div>
    );
  };

  export default ParentComponent;
  3. 常见用法
  - 封装组件逻辑：通过  `useImperativeHandle` ，可以将组件的某些方法暴露给父组件，而不需要直接暴露整个组件实例。
  - 简化父组件逻辑：父组件可以通过自定义的 ref 方法直接与子组件交互，减少了父组件对子组件内部实现的依赖。

  4. 注意事项
  - 性能考虑：使用  `useImperativeHandle`  时，确保只暴露必要的方法，以避免不必要的复杂性。
  - 与  `forwardRef`  配合： `useImperativeHandle`  必须与  `forwardRef`  一起使用，以便能够正确接收和处理  `ref` 。

  5. 总结
  `useImperativeHandle`  是一个强大的工具，允许开发者自定义通过  `ref`  暴露给父组件的实例值。它与  `forwardRef`  结合使用，可以有效地封装组件逻辑，简化父组件的交互。通过合理使用  `useImperativeHandle` ，可以提高组件的可维护性和可重用性。
 */
import React, { memo, useRef, forwardRef, useImperativeHandle } from 'react'

const Home = memo(forwardRef((props, ref) => {
  const inputRef = useRef()
  
  // 子组件对父组件传入的ref进行处理
  useImperativeHandle(ref, () => {
    return {
      focus: () => {
        console.log("focus");
        inputRef.current.focus()
      },
      setValue(value) {
        inputRef.current.value = value
      }
    }
  })

  return (
    <input type="text" ref={inputRef} />
  )
}))

const App = memo(() => {
  const titleRef = useRef()
  const inputRef = useRef()

  function handleDOM() {
    // console.log(inputRef.current)
    inputRef.current.focus()
    // inputRef.current.value = ""
    inputRef.current.setValue("useImperativeHandle-setValue")
  }
  
  return (
    <div>
      <h2 ref={titleRef}>useImperativeHandle使用</h2>
      <Home ref={inputRef}/>
      <button onClick={handleDOM}>DOM操作</button>
    </div>
  )
})

export default App